<?php
/**
 * Description: 直播课列表
 * User: devforma
 * Date: 15/6/6
 * Time: 13:25
 */

require LIB_DIR . '/LiveCourse.class.php';
class GetCourseList implements iController {
    private $userId, $loginStatus;
    private $shownCourseGroups;
    private $lectorId = 0;
    private $terminalType;

    /**
     * api请求处理主函数
     * @param array $queryArgs 就是$_REQUEST变量
     * @return array api返回结果，必须含response_code
     */
    public function output($queryArgs) {

        $this->loginStatus = validateUser($queryArgs); //登录状态，1表示登录，3表示未登录

        $this->terminalType = empty($queryArgs['terminal_type']) ? 'pc_web' : $queryArgs['terminal_type'];

        if (!empty($queryArgs['lector_id']) && filter_var($queryArgs['lector_id'], FILTER_VALIDATE_INT))
            $this->lectorId = $queryArgs['lector_id'];

        $this->userId = $queryArgs['user_id'];

        //获取已购课程列表
        if ($this->loginStatus === 1) {
            $purchasedCourses = $this->getPurchasedCourses($queryArgs['user_id']);

        } else {
            $purchasedCourses = array(
                'vod_course' => array(),
                'live_course' => array()
            );;
        }

        $tag            = !empty($queryArgs['tag']) ? (int)$queryArgs['tag'] : 0;
        $isPurchased    = isset($queryArgs['is_purchased']) ? (int)$queryArgs['is_purchased'] : 2;
        $area           = !empty($queryArgs['area']) ? $queryArgs['area'] : 'ALL';
        $examType       = !empty($queryArgs['exam_type']) ? $queryArgs['exam_type'] : '';
        $startPrice     = isset($queryArgs['start_price']) ? (int)$queryArgs['start_price'] : -1;
        $endPrice       = isset($queryArgs['end_price']) ? (int)$queryArgs['end_price'] : -1;

        //筛选合适的直播课
        $liveCourse = $this->getLiveCourses($purchasedCourses['live_course'], $tag, $isPurchased, $area, $examType, $startPrice, $endPrice);

        return genOutput(1, array(
            'courses' => $liveCourse
        ));
    }


    /**
     * 获取符合条件的直播课
     * @param array $purchasedCourses 已购id数组
     * @param int $tag 标签id
     * @param int $purchased 购买状态
     * @param string $areaCode 地区码
     * @param string $examType 考试类别
     * @param int $startPrice 开始价格
     * @param int $endPrice 结束价格
     * @return array
     */
    private function getLiveCourses($purchasedCourses, $tag, $purchased, $areaCode, $examType, $startPrice, $endPrice) {
        global $cmsdb;

        if ($purchased == 1 && empty($purchasedCourses)) //没购买过课程却要查看已购
            return array();

        $now = time();


        /**---------------------------------------------------------------------------
        | 构造课程查询语句
        ---------------------------------------------------------------------------*/
        $sql = 'SELECT c.* FROM `data_live_course` AS c';
        if (!empty($tag)) {
            $sql .= ' INNER JOIN `relation_course_category` AS r ON c.id=r.live_course_id WHERE r.category_id='.$tag;
        } else {
            $sql .= ' WHERE 1';
        }

        //考试类别
        if (!empty($examType)) {
            $sql .= ' AND c.exam_type=:exam_type';
        }

        //价格区间
        if ($startPrice != -1 && $endPrice != -1) {
            $sql .= " AND c.price>={$startPrice} AND c.price<={$endPrice}";
        }

        $sql .= " AND c.type_id!=1 AND UNIX_TIMESTAMP(`start_day`)<={$now}";

        if ($purchased == 1 && empty($purchasedCourses)) { //请求已购，没买过课
            return array();

        } elseif ($purchased == 1 && !empty($purchasedCourses)) { //请求已购，买过课
            $str = implode(',', $purchasedCourses);
            $sql .= " AND c.id IN ({$str})";

        } elseif ($purchased == 0 && empty($purchasedCourses)) { //请求未购，没买过课
            $sql .= " AND c.publish_status='publish' AND (UNIX_TIMESTAMP(`end_day`)>{$now} OR `end_day`='0000-00-00 00:00:00')";

        } elseif ($purchased == 0 && !empty($purchasedCourses)) { //请求未购，买过课
            $str = implode(',', $purchasedCourses);
            $sql .= " AND c.publish_status='publish' AND c.id NOT IN ({$str}) AND (UNIX_TIMESTAMP(`end_day`)>{$now} OR `end_day`='0000-00-00 00:00:00')";

        } elseif ($purchased == 2 && empty($purchasedCourses)) { //请求所有，没买过课
            $sql .= " AND c.publish_status='publish' AND (UNIX_TIMESTAMP(`end_day`)>{$now} OR `end_day`='0000-00-00 00:00:00')";

        } elseif ($purchased == 2 && !empty($purchasedCourses)) { //请求所有，买过课
            $str = implode(',', $purchasedCourses);
            $sql .= " AND c.publish_status='publish' AND (c.id IN ({$str}) OR (c.id NOT IN ({$str}) AND
            (UNIX_TIMESTAMP(`end_day`)>{$now} OR `end_day`='0000-00-00 00:00:00')))";
        }

        if ($purchased == 1) {
            $sql .= " ORDER BY c.id DESC"; //公共过滤条件及排序
        } else {

            //置顶顺序区分PC端和移动端
            if ($this->terminalType === 'pc_web') {
                $sql .= " ORDER BY c.is_sticked DESC, c.last_modified DESC, c.id DESC"; //公共过滤条件及排序
            } else {
                $sql .= " ORDER BY c.app_is_sticked DESC, c.app_last_modified DESC, c.id DESC"; //公共过滤条件及排序
            }
        }

        if (!empty($examType)) {
            $courses = $cmsdb->getResults($sql, [':exam_type' => $examType]);
        } else {
            $courses = $cmsdb->getResults($sql);
        }
        
        if (empty($courses))
            return array();


        /**---------------------------------------------------------------------------
        | 对课程列表进行过滤
        ----------------------------------------------------------------------------*/
        //默认情况下，地区编码统一为ALL
        if ($areaCode == 'DEFAULT') $areaCode = 'ALL';

        $results = array();
        foreach ($courses as $c) {
            //设置购买状态
            $isPurchased = in_array($c->id, $purchasedCourses, true);

            //地域过滤，若课程的地区设置与用户的考试项目不一致则过滤
            if (!$isPurchased && $areaCode != 'ALL' && $c->related_test_shortening != 'ALL'
                && strpos($c->related_test_shortening, $areaCode) === false) {
                continue;
            }

            $realStartTime = $c->class_starttime; //第一节课开始时间
            $realEndTime   = $c->class_endtime;   //最后一节课结束时间

            //无下架时间的课程以最后一节课结束时间为下架时间
            if ($c->end_day == '0000-00-00 00:00:00') {
                $c->end_day = $realEndTime;
            }

            //过期且未购买则过滤掉
            if (!$isPurchased && strtotime($c->end_day) < $now)
                continue;

            //获取购课人数
            $persons = getCoursePurchasedPersons($c->id);
            $isFull = $persons >= $c->student_limit && $c->student_limit != -1;

            //购买人数已达上限则过滤掉
            if (!$isPurchased && $isFull && !$c->show_after_soldout)
                continue;

            $computedCourseInfo = LiveCourse::getComputedCourseInfo($c->id); //课程计算属性
            $todayClasses       = $computedCourseInfo['today_classes'];      //今天上课的课堂
            $totalSeconds       = $computedCourseInfo['periods'];            //总时长
            $teachers           = $computedCourseInfo['lectors'];            //课程包含的教师

            //设置课程状态
            if ($computedCourseInfo['is_onair'])    //正在上课
                $status = 'on_air';
            elseif (strtotime($realEndTime) < $now) //课程结束，状态为看回放
                $status = 'replay';
            else                                    //下堂课还未开始
                $status = 'unstart';

            //根据教师来查询课程,其他教师的课和已下架的课不再显示
            if (!empty($this->lectorId) && (!isset($teachers[$this->lectorId]) || strtotime($c->end_day) < $now)) {
                continue;
            }

            //跳转详情页面url
            $detailPage = $isPurchased ? YG_MOBILE_SECURE_URL . '/index.html#/live/purchased?'
                : YG_MOBILE_SECURE_URL . '/index.html#/live/unpurchased?';

            //可购买时间
            $timeCanPurchase = strtotime($c->time_can_purchase);

            //虚拟购买人数
            $extraNumber = $c->id == '1526' ? getExtraPurchasedNum('2016-10-12 18:05:00', 10, 2) : 0;

            $personsNum = intval($persons) + $extraNumber;
            if ($c->student_limit != -1 && $personsNum > $c->student_limit) {
                $personsNum = (int)$c->student_limit;
            }

            $course = array(
                'id' => intval($c->id),
                'type' => 'live',
                'name' => $c->course_name,
                'introduction' => $c->introduction,
                'lectors' => array_values($teachers),
                'is_purchased' => $isPurchased,
                'can_purchase' => $c->time_can_purchase == '0000-00-00 00:00:00' || $timeCanPurchase <= $now ? true : false,
                'can_purchase_time' => date('Y/m/d H:i', $timeCanPurchase),
                'status' => $status,
                'is_sticked' => $c->is_sticked ? true : false,
                'detail_page' => $detailPage,
                'timeStr' => $c->course_desc,
                'start_time' => $this->calShowStartTime($realStartTime, $c->course_desc),
                'end_time' => $this->calShowEndTime($realEndTime, $c->course_desc),
                'price' => floatval($c->price),
                'student_limit' => intval($c->student_limit),
                'persons_num' => $personsNum,
                'type_id' => intval($c->type_id),
                'is_vipcourse' => $c->type_id == 9, //小班
                'valid_order_num' => 0,
                'periods' => $this->getCoursePeriod($totalSeconds, empty($c->course_hour) ? 0 : $c->course_hour),
                'cover_pic' => empty($c->cover_pic) ? '' : getSecureUrl($c->cover_pic),
                'today_classes' => $todayClasses,
                'show_after_soldout' => !empty($c->show_after_soldout),
                'is_onsale' => strtotime($c->start_day) <= $now && strtotime($c->end_day) > $now
            );

            //购课时限
            $course['deadline'] = $c->end_day === '0000-00-00 00:00:00' ? $realEndTime : $c->end_day;

            //课程组处理逻辑
            if (!empty($c->course_group_id)) {

                //该课程组首次出现,初始化该课程组信息
                if (!isset($this->shownCourseGroups[$c->course_group_id])) {
                    $this->shownCourseGroups[$c->course_group_id] = [
                        'position'  => count($results) + count($this->shownCourseGroups),
                        'courses'   => [],
                        'purchased' => false
                    ];
                }

                //课程组添加课程
                $this->shownCourseGroups[$c->course_group_id]['courses'][$c->id] = $course;

                //课程组已购状态更新(只要一个课程已购则课程组已购)
                if ($isPurchased)
                    $this->shownCourseGroups[$c->course_group_id]['purchased'] = true;

                continue;
            }

            $results[] = $course;
        }


        //课程组逻辑处理
        foreach ($this->shownCourseGroups as $group) {
            if ($group['purchased']) {
                $purchased   = array();   //已购
                foreach ($group['courses'] as $groupKey => $groupCourse) {
                    if ($groupCourse['is_purchased'] == true) {    //取出所有已购买课程
                        $purchased[] = $groupCourse;
                    } elseif ($groupCourse['is_onsale']) {
                        $purchased[] = $groupCourse;
                    }
                }

                array_splice($results, $group['position'], 0, $purchased);

            } else { //如果课程组未购,则显示组内第一个课程
                ksort($group['courses']);
                $propCourse = array_shift($group['courses']);

                array_splice($results, $group['position'], 0, [$propCourse]);
            }
        }

        return $results;
    }

    /**
     * 读取课程的课时，按照每堂课的时间加起来*4/3来计算，四舍五入
     * @param $totalSeconds
     * @param $courseHours
     * @return float|int
     */
    private function getCoursePeriod($totalSeconds, $courseHours) {
        $calhours = round($totalSeconds * 4 / (3600*3));

        return max($calhours, intval($courseHours));
    }

    /**
     * 获取用户购买的课程id
     * @param int $userId 用户id
     * @return array
     */
    private function getPurchasedCourses($userId) {
        global $cmsdb;

        //返回结果
        $result = array(
            'vod_course' => array(),
            'live_course' => array()
        );

        $buyed = $cmsdb->getResults('SELECT `product_id`, `product_type` FROM `relation_user_product` WHERE `user_id`=:uid',
            array(':uid' => $userId));

        if (empty($buyed))
            return $result;

        //构造返回结果
        foreach ($buyed as $record) {
            if ($record->product_type == 'zhiboke' && !in_array($record->product_id, $result['live_course'], true))
                $result['live_course'][] = $record->product_id;

            elseif ($record->product_type == 'course' && !in_array($record->product_id, $result['vod_course'], true))
                $result['vod_course'][] = $record->product_id;
        }

        return $result;
    }


    /**
     * 计算供显示的开始时间(由课堂开始时间和手填的课程时间说明(格式:2015.01.10[-2015.04.12])共同决定)
     *
     * @param string $classStartTime 课堂开始时间
     * @param string $courseDateDesc 手填的课程时间说明
     * @return mixed
     */
    private function calShowStartTime($classStartTime, $courseDateDesc) {
        $times = explode('-', $courseDateDesc);
        $times[0] = str_replace('.', '-', $times[0]);

        $t = strtotime($times[0]);

        return $t == false ? $classStartTime : date('Y-m-d H:i:s', $t);
    }

    /**
     * 计算供显示的结束时间(由课堂开始时间和手填的课程时间说明(格式:2015.01.10[-2015.04.12])共同决定)
     *
     * @param string $classEndTime 课堂结束时间
     * @param string $courseDateDesc 手填的课程时间说明
     * @return mixed
     */
    private function calShowEndTime($classEndTime, $courseDateDesc) {
        $times = explode('-', $courseDateDesc);
        if (!isset($times[1]))
            return $classEndTime;

        $times[1] = str_replace('.', '-', $times[1]);
        $t = strtotime($times[1]);

        return $t == false ? $classEndTime : date('Y-m-d H:i:s', $t);
    }
}